﻿using System.IO;
using BruteForceSerializer.Contract.Internal;
using Newtonsoft.Json;

namespace BruteForceSerializer.Formatting
{
    internal static class Formatter
    {
        public static string Format(INormalizedObject objectGraphRoot, bool indent)
        {
            using(var sw = new StringWriter())
            {
                var jtw = new JsonTextWriter(sw);
                if (indent) jtw.Formatting = Newtonsoft.Json.Formatting.Indented;

                Format(jtw, objectGraphRoot);

                return sw.ToString();
            }
        }

        private static void Format(JsonTextWriter jtw, INormalizedObject objectGraphRoot)
        {
            if (objectGraphRoot == null) {
                jtw.WriteNull();
                return;
            }

            jtw.WriteStartObject();

            Write_JSON_Object(jtw, objectGraphRoot);

            jtw.WriteEndObject();
        }


        private static void Write_JSON_Object(JsonTextWriter jtw, INormalizedObject objectGraphRoot)
        {
            Write_object_header(jtw, objectGraphRoot);
            Write_object_fields(jtw, objectGraphRoot);
        }


        private static void Write_object_header(JsonTextWriter jtw, INormalizedObject objectGraphRoot)
        {
            jtw.WritePropertyName("_Id");
            jtw.WriteValue(objectGraphRoot.Id);

            jtw.WritePropertyName("_Type");
            jtw.WriteValue(objectGraphRoot.Typename);
        }

        private static void Write_object_fields(JsonTextWriter jtw, INormalizedObject objectGraphRoot)
        {
            foreach (var field in objectGraphRoot.Fields)
            {
                jtw.WritePropertyName(field.Name);
                if (field.Value is INormalizedObject)
                    Format(jtw, (INormalizedObject)field.Value);
                else if (field.Value is INormalizedReference)
                    Write_object_reference(jtw, field);
                else
                    jtw.WriteValue(field.Value);
            }
        }

        private static void Write_object_reference(JsonTextWriter jtw, INormalizedField field)
        {
            jtw.WriteStartObject();

            jtw.WritePropertyName("_ObjectId");
            jtw.WriteValue(((INormalizedReference)field.Value).ObjectId);

            jtw.WriteEndObject();
        }
    }
}
